package me.zhengjie.service.impl;

import lombok.RequiredArgsConstructor;
import me.zhengjie.WcsReport.WcsReportService;
import me.zhengjie.pojo.dto.*;
import me.zhengjie.pojo.entity.*;
import me.zhengjie.pojo.vo.AgvTaskSubmitVo;
import me.zhengjie.service.AgvReturnService;
import me.zhengjie.sqlservice.*;
import me.zhengjie.tcp.ChainLineTCP;
import me.zhengjie.tcp.FluentFrameTCPA;
import me.zhengjie.tcp.FluentFrameTCPB;
import me.zhengjie.util.liftState.LiftTaskStatus;
import me.zhengjie.util.state.MaterialStatus;
import me.zhengjie.util.state.TaskStatus;
import me.zhengjie.util.state.TaskType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class AgvReturnServiceImpl implements AgvReturnService {
    private static final Logger haikang = LoggerFactory.getLogger("haiKang");
    private static final Logger liftLog = LoggerFactory.getLogger("lift");

    private final WcsInboundMissionService wcsInboundMissionService;

    private final ChainLineTCP chainLineTCP;

    private final WcsChainLineConfigService wcsChainLineConfigService;

    private final WcsReportService wcsReportService;

    private final WcsOutboundMissionService wcsOutboundMissionService;

    private final WcsInboundMissionHistoryService wcsInboundMissionHistoryService;

    private final WcsOutboundMissionHistoryService wcsOutboundMissionHistoryService;

    private final IwsSOutsideService iwsSOutsideService;

    private final WcsDeliveryMissionService wcsDeliveryMissionService;

    private final WcsDeliveryMissionHistoryService wcsDeliveryMissionHistoryService;

    private final WcsInboundAbnormalMissionService wcsInboundAbnormalMissionService;

    private final WcsInboundAbnormalMissionHistoryService wcsInboundAbnormalMissionHistoryService;

    private final WcsFluentFrameConfigService wcsFluentFrameConfigService;

    private final LiftWaitPointService liftWaitPointService;

    private final LiftSqlService liftSqlService;

    private final LiftTaskService liftTaskService;

    private final FluentFrameTCPA fluentFrameTCPA;

    private final FluentFrameTCPB fluentFrameTCPB;


    @Transactional
    @Override
    public AgvTaskSubmitVo agvTaskReport(AgvReturnDto agvReturnDto) {
        String robotTaskCode = agvReturnDto.getRobotTaskCode();
        haikang.info("海康上报取放货接口：{}",agvReturnDto);
        //根据任务号判断入库任务还是出库任务
        WcsInboundMission wcsInboundMission = wcsInboundMissionService.selectInboundCode(robotTaskCode);
        WcsOutboundMission wcsOutboundMission = wcsOutboundMissionService.selectOutboundCode(robotTaskCode);
        WcsDeliveryMission wcsDeliveryMission = wcsDeliveryMissionService.selectDeliveryCode(robotTaskCode);
        WcsInboundAbnormalMission wcsInboundAbnormalMission = wcsInboundAbnormalMissionService.selectInboundAbnormalCode(robotTaskCode);
        haikang.info("agv任务上报查询结果入库;{},出库：{},配送：{},入库异常：{},",wcsInboundMission,wcsOutboundMission,wcsDeliveryMission,wcsInboundAbnormalMission);
        if (wcsInboundMission != null) {
            Integer id = wcsInboundMission.getId();
            String containerCode = wcsInboundMission.getContainerCode();
            String destination = wcsInboundMission.getDestination();
            String source = wcsInboundMission.getSource();
            String taskType = wcsInboundMission.getTaskType();
            Integer inboundType = wcsInboundMission.getInboundType();
            Integer isNest = wcsInboundMission.getIsNest();
            Integer containerType = wcsInboundMission.getContainerType();
            Integer isPlc = wcsInboundMission.getIsPlc();
            String wmsTaskId = wcsInboundMission.getWmsTaskId();
            String inboundCode = wcsInboundMission.getInboundCode();
            Extra extra = agvReturnDto.getExtra();
            Values values = extra.getValues();
            String method = values.getMethod();
            if ("start".equals(method)) {
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("outbin".equals(method)) {
                //入库任务，agv取货完成
                String carrierName = values.getCarrierName();
                boolean b = wcsInboundMissionService.updateMissionStatusAndAgvId(id, TaskStatus.task_take.getStatus(), carrierName);
                if (!b) {
                    haikang.error("agv上报取货，修改数据库失败，数据库异常");
                    throw new RuntimeException("agv上报取货，修改数据库失败，数据库异常");
                }
                //判断入库任务是否是否是栈板入库，是就要发送给PLC容器被AGV取走

                if (isPlc == 1) {
                    if (containerType == 1){
                        //1楼入库，需要给PLC发送容器取走
                        WcsChainLineConfig wcsChainLineConfig = wcsChainLineConfigService.selectTransportStorage(wcsInboundMission.getSource());
                        if (wcsChainLineConfig != null){
                            Integer threeReturnResult = wcsChainLineConfig.getThreeReturnResult();
                            Integer unitId = wcsChainLineConfig.getUnitId();
                            chainLineTCP.writeWithRetry(threeReturnResult, MaterialStatus.AGV_MOVED.getStatus(), unitId, MaterialStatus.RETRY_COUNT.getStatus());
                        }
                    }else if (containerType == 2){
                        WcsFluentFrameConfig wcsFluentFrameConfig = wcsFluentFrameConfigService.selectStorageCode(source);
                        if (wcsFluentFrameConfig !=null){
                            String region = wcsFluentFrameConfig.getRegion();
                            Integer threeReturnResult = wcsFluentFrameConfig.getThreeReturnResult();
                            Integer unitId = wcsFluentFrameConfig.getUnit_id();
                            if (Objects.equals(region, "A")){
                                fluentFrameTCPA.writeWithRetry(threeReturnResult,MaterialStatus.AGV_TRANSPORT_COMPLETE.getStatus(),unitId,MaterialStatus.RETRY_COUNT.getStatus());
                            }else if (Objects.equals(region, "B")){
                                fluentFrameTCPB.writeWithRetry(threeReturnResult,MaterialStatus.AGV_TRANSPORT_COMPLETE.getStatus(),unitId,MaterialStatus.RETRY_COUNT.getStatus());
                            }
                        }

                    }else if (containerType == 3){

                    }
                }
//                if (TaskType.circle_library_sorting.getStatus().equals(inboundType)){
                    //通知WMS取货完成
                    takeReportDto takeReportDto = new takeReportDto();
                    takeReportDto.setContainerCode(containerCode);
                    takeReportDto.setStorageCode(source);
                    takeReportDto.setType(TaskType.OUTBOUND_TAKE_BOX.getStatus());
                    takeReportDto.setTaskType(taskType);
                    takeReportDto.setBoundType(1);
                    takeReportDto.setWmsTaskId(wmsTaskId);
                    if (isNest ==1){
                        takeReportDto.setNest(true);
                    }else {
                        takeReportDto.setNest(false);
                    }
//                    wcsReportService.pickPlaceReport(takeReportDto);
//                }
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("end".equals(method)) {
                //判断入库任务储位是否是库外储位，是将储位释放
//                iwsSOutsideService.updateStatus(destination,containerCode,3);
                //agv入库任务完成。修改状态，移到历史表，通知WMS入库
//                boolean b = wcsInboundMissionService.updateMissionStatus(robotTaskCode, TaskStatus.task_put.getStatus());
//                if (!b) {
//                    haikang.error("AGV放货完成，修改数据库状态失败");
//                    throw new RuntimeException("AGV放货完成，修改数据库状态失败");
//                }
                //移到历史表
//                WcsInboundMissionHistory wcsInboundMissionHistory = new WcsInboundMissionHistory();
//                BeanUtils.copyProperties(wcsInboundMission, wcsInboundMissionHistory);
//                wcsInboundMissionHistory.setId(null);
//                wcsInboundMissionHistory.setMissionStatus(TaskStatus.Task_complete.getStatus());
//                boolean b3 = wcsInboundMissionHistoryService.insertInboundHistory(wcsInboundMissionHistory);
//                if (b3){
//                    haikang.error("海康上报入库放货，插入历史表失败");
//                }
                //上报WMS栈板入库
                takeReportDto takeReportDto = new takeReportDto();
                takeReportDto.setContainerCode(containerCode);
                takeReportDto.setStorageCode(destination);
                takeReportDto.setType(TaskType.OUTBOUND_PUT_BOX.getStatus());
                takeReportDto.setTaskType(taskType);
                takeReportDto.setBoundType(1);
                takeReportDto.setWmsTaskId(wmsTaskId);
                if (isNest ==1){
                    takeReportDto.setNest(true);
                }else {
                    takeReportDto.setNest(false);
                }
//                boolean b2 = wcsReportService.pickPlaceReport(takeReportDto);

                //删除入库任务
//                boolean b1 = wcsInboundMissionService.deleteInboundId(wcsInboundMission.getId());
                boolean b1 = wcsInboundMissionService.updateMissionStatus(inboundCode,TaskStatus.Task_complete.getStatus());
                return AgvTaskSubmitVo.OK(robotTaskCode);
            }else if ("middle".equals(method)){
                //中间点上报，占用储位
                iwsSOutsideService.updateStatus(TaskType.ONE_FLOOR_RETURN_TO_STORAGE_LOCATION.getMessage(),containerCode,3);
                return AgvTaskSubmitVo.OK(robotTaskCode);
            }
        }else if (wcsOutboundMission !=null){
            //出库上报
            Extra extra = agvReturnDto.getExtra();
            Values values = extra.getValues();
            String method = values.getMethod();
            Integer id = wcsOutboundMission.getId();
            String outboundContainerCode = wcsOutboundMission.getContainerCode();
            String source = wcsOutboundMission.getSource();
            String destination = wcsOutboundMission.getDestination();
            String taskType = wcsOutboundMission.getTaskType();
            Integer containerType = wcsOutboundMission.getContainerType();
            Integer isNest = wcsOutboundMission.getIsNest();
            String wmsTaskId = wcsOutboundMission.getWmsTaskId();
            String outboundCode = wcsOutboundMission.getOutboundCode();
            if ("start".equals(method)) {
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("outbin".equals(method)) {
                //入库任务，agv取货完成
                String carrierName = values.getCarrierName();
                boolean b = wcsOutboundMissionService.updateMissionStatusAndAgvId(id, TaskStatus.task_take.getStatus(), carrierName);
                if (!b) {
                    haikang.error("agv出库上报取货，修改数据库失败，数据库异常");
                    throw new RuntimeException("agv出库上报取货，修改数据库失败，数据库异常");
                }
                //发送WMS出库取货
                takeReportDto takeReportDto = new takeReportDto();
                takeReportDto.setContainerCode(outboundContainerCode);
                takeReportDto.setStorageCode(source);
                takeReportDto.setType(TaskType.OUTBOUND_TAKE_BOX.getStatus());
                takeReportDto.setTaskType(taskType);
                takeReportDto.setBoundType(2);
                takeReportDto.setWmsTaskId(wmsTaskId);
                if (isNest ==1){
                    takeReportDto.setNest(true);
                }else {
                    takeReportDto.setNest(false);
                }
                boolean b2 = wcsReportService.pickPlaceReport(takeReportDto);
                if (!b2){
                    haikang.error("出库放货修改数据库失败");
                    throw new RuntimeException("出库放货修改数据库失败");
                }
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("end".equals(method)) {
                //agv入库任务完成。修改状态，移到历史表，通知WMS入库
//                boolean b = wcsOutboundMissionService.updateMissionStatus(robotTaskCode, TaskStatus.task_put.getStatus());
//                if (!b) {
//                    haikang.error("AGV出库放完成，修改数据库状态失败");
//                    throw new RuntimeException("AGV出库放货完成，修改数据库状态失败");
//                }
                //移到历史表
//                WcsOutboundMissionHistory wcsOutboundMissionHistory = new WcsOutboundMissionHistory();
//                BeanUtils.copyProperties(wcsOutboundMission, wcsOutboundMissionHistory);
//                wcsOutboundMissionHistory.setId(null);
//                wcsOutboundMissionHistory.setMissionStatus(TaskStatus.Task_complete.getStatus());
//                boolean b3 = wcsOutboundMissionHistoryService.insertOutboundHistory(wcsOutboundMissionHistory);
                //1楼托盘出库上报WMS栈板入库
                if (Objects.equals(TaskType.PALLET.getStatus(), containerType)){
                    //1楼出库上报放货完成
                    takeReportDto takeReportDto = new takeReportDto();
                    takeReportDto.setContainerCode(outboundContainerCode);
                    takeReportDto.setStorageCode(destination);
                    takeReportDto.setType(TaskType.OUTBOUND_PUT_BOX.getStatus());
                    takeReportDto.setTaskType(taskType);
                    takeReportDto.setBoundType(2);
                    takeReportDto.setWmsTaskId(wmsTaskId);
                    if (isNest ==1){
                        takeReportDto.setNest(true);
                    }else {
                        takeReportDto.setNest(false);
                    }
                    boolean b2 = wcsReportService.pickPlaceReport(takeReportDto);
                    if (!b2){
                        haikang.error("出库放货修改数据库失败");
                        throw new RuntimeException("出库放货修改数据库失败");
                    }
                }
                if (Objects.equals(TaskType.EMPTY_MATERIAL_BOX.getStatus(), containerType)){
                    //空箱出库，需要扣减数量
                    WcsFluentFrameConfig wcsFluentFrameConfig = wcsFluentFrameConfigService.selectStorageCode(destination);
                    if (wcsFluentFrameConfig !=null){
                        Integer fluentFrameConfigId = wcsFluentFrameConfig.getId();
                        Integer size = wcsFluentFrameConfig.getSize();
                        size--;
                        //扣减数量
                        wcsFluentFrameConfigService.updateSize(fluentFrameConfigId,size);
                    }
                }
                //删除出库任务
                boolean b1 = wcsOutboundMissionService.updateMissionStatus(outboundCode,TaskStatus.Task_complete.getStatus());
                if (!b1){
                    haikang.error("出库放货完成，移到历史表失败");
                    throw new RuntimeException("出库放货完成，移到历史表失败");
                }
                return AgvTaskSubmitVo.OK(robotTaskCode);
            }
        }else if (wcsDeliveryMission != null){
            Integer id = wcsDeliveryMission.getId();
            String containerCode = wcsDeliveryMission.getContainerCode();
            String destination = wcsDeliveryMission.getDestination();
            String source = wcsDeliveryMission.getSource();
            String deliveryCode = wcsDeliveryMission.getDeliveryCode();
            Extra extra = agvReturnDto.getExtra();
            Values values = extra.getValues();
            String method = values.getMethod();
            if ("start".equals(method)) {
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("outbin".equals(method)) {
                //配送任务，agv取货完成
                String carrierName = values.getCarrierName();
                boolean b = wcsDeliveryMissionService.updateDeliveryStatusAndAgvId(id, TaskStatus.task_take.getStatus(), carrierName);
                if (!b) {
                    haikang.error("agv配送任务上报取货，修改数据库失败，数据库异常");
                    throw new RuntimeException("agv配送任务上报取货，修改数据库失败，数据库异常");
                }
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("end".equals(method)) {
                //判断入库任务储位是否是库外储位，是将储位释放
//                IwsSOutside iwsSOutside = iwsSOutsideService.selectStorageCode(destination);
//                if (iwsSOutside !=null){
//                }
                iwsSOutsideService.updateStatus(destination,containerCode,3);
                //agv入库任务完成。修改状态，移到历史表，通知WMS入库
//                boolean b = wcsDeliveryMissionService.updateMissionStatus(robotTaskCode, TaskStatus.task_put.getStatus());
//                if (!b) {
//                    haikang.error("AGV放货完成，修改数据库状态失败");
//                    throw new RuntimeException("AGV放货完成，修改数据库状态失败");
//                }
                //移到历史表
//                WcsDeliveryMissionHistory wcsDeliveryMissionHistory = new WcsDeliveryMissionHistory();
//                BeanUtils.copyProperties(wcsDeliveryMission, wcsDeliveryMissionHistory);
//                wcsDeliveryMissionHistory.setId(null);
//                wcsDeliveryMissionHistory.setMissionStatus(TaskStatus.Task_complete.getStatus());
//                boolean b3 = wcsDeliveryMissionHistoryService.insertDeliveryHistory(wcsDeliveryMissionHistory);
//                if (!b3){
//                    haikang.error("海康上报入库放货，插入历史表失败");
//                }
                //删除入库任务
                boolean b1 = wcsDeliveryMissionService.updateMissionStatus(deliveryCode,TaskStatus.Task_complete.getStatus());
                return AgvTaskSubmitVo.OK(robotTaskCode);
            }
        }else if (wcsInboundAbnormalMission !=null){
            Integer id = wcsInboundAbnormalMission.getId();
            String containerCode = wcsInboundAbnormalMission.getContainerCode();
            String destination = wcsInboundAbnormalMission.getDestination();
            String abnormalCode = wcsInboundAbnormalMission.getAbnormalCode();
            Extra extra = agvReturnDto.getExtra();
            Values values = extra.getValues();
            String method = values.getMethod();
            if ("start".equals(method)) {
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("outbin".equals(method)) {
                //配送任务，agv取货完成
                String carrierName = values.getCarrierName();
                boolean b = wcsInboundAbnormalMissionService.updateAbnormalStatusAndAgvId(id, TaskStatus.task_take.getStatus(), carrierName);
                if (!b) {
                    haikang.error("agv配送任务上报取货，修改数据库失败，数据库异常");
                    throw new RuntimeException("agv配送任务上报取货，修改数据库失败，数据库异常");
                }
                return AgvTaskSubmitVo.OK(robotTaskCode);
            } else if ("end".equals(method)) {
                //判断入库任务储位是否是库外储位，是将储位释放
//                IwsSOutside iwsSOutside = iwsSOutsideService.selectStorageCode(destination);
//                if (iwsSOutside !=null){
//                }
                iwsSOutsideService.updateStatus(destination,containerCode,3);
                //agv入库任务完成。修改状态，移到历史表，通知WMS入库
//                boolean b = wcsInboundAbnormalMissionService.updateMissionStatus(robotTaskCode, TaskStatus.task_put.getStatus());
//                if (!b) {
//                    haikang.error("AGV放货完成，修改数据库状态失败");
//                    throw new RuntimeException("AGV放货完成，修改数据库状态失败");
//                }
                //移到历史表
//                WcsInboundAbnormalMissionHistory wcsInboundAbnormalHistoryMission = new WcsInboundAbnormalMissionHistory();
//                BeanUtils.copyProperties(wcsInboundAbnormalMission,wcsInboundAbnormalHistoryMission );
//                wcsInboundAbnormalHistoryMission.setId(null);
//                wcsInboundAbnormalHistoryMission.setMissionStatus(TaskStatus.Task_complete.getStatus());
//                boolean b3 = wcsInboundAbnormalMissionHistoryService.insertAbnormalHistory(wcsInboundAbnormalHistoryMission);
//                if (b3){
//                    haikang.error("海康上报入库放货，插入历史表失败");
//                }
                //删除入库任务
                boolean b1 = wcsInboundAbnormalMissionService.updateMissionStatus(abnormalCode,TaskStatus.Task_complete.getStatus());
                if (!b1) {
                    haikang.error("AGV放货完成，修改数据库状态失败");
                    throw new RuntimeException("AGV放货完成，修改数据库状态失败");
                }
                return AgvTaskSubmitVo.OK(robotTaskCode);
            }
        }
        return AgvTaskSubmitVo.ng(robotTaskCode);
    }

    @Transactional
    @Override
    public AgvTaskSubmitVo agvRequestLift(AgvRequestLiftDto agvRequestLiftDto) {
        haikang.info("请求电梯请求参数：{}",agvRequestLiftDto);
        //设备编号
        String eqptCode = agvRequestLiftDto.getEqptCode();
        //设备名称
//        String eqptName = agvRequestLiftDto.getEqptName();
        //任务号为唯一编号，可使用 UUID
        String taskCode = agvRequestLiftDto.getTaskCode();
        //任务执行方法，与设备相关，可扩展枚举值。
        String method = agvRequestLiftDto.getMethod();
        //起点
        String srcCode = agvRequestLiftDto.getSrcCode();
        //终点
        String dstCode = agvRequestLiftDto.getDstCode();

        if (LiftTaskStatus.APPLY_RESOURCE.getMessage().equals(method)){
            LiftWaitPoint liftWaitPoint = new LiftWaitPoint();
            liftWaitPoint.setLiftCode(eqptCode);
            liftWaitPoint.setTaskCode(taskCode);
            liftWaitPoint.setStartFloor(srcCode);
            liftWaitPoint.setEndFloor(dstCode);
            liftWaitPoint.setCreateTime(LocalDateTime.now());
            //电梯任务创建
            boolean b = liftWaitPointService.insertLiftWaitPoint(liftWaitPoint);
            if (!b){
                haikang.error("创建电梯等待点失败，数据库异常");
                throw new RuntimeException("创建电梯等待点失败，数据库异常");
            }
            return AgvTaskSubmitVo.OK(null);
        }else if (LiftTaskStatus.EXECUTE_TASK.getMessage().equals(method)){
            LiftTask liftTask = liftTaskService.selectLIftTask(taskCode);
            //AGV上报到达电梯储位，修改电梯任务状态
            boolean b1 = liftTaskService.updateStatus(liftTask.getId(), LiftTaskStatus.ARRIVE_STORAGE_POINT.getCode());
            if (!b1){
                liftLog.error("修改电梯任务状态为4，数据库异常，回滚");
                throw new RuntimeException("修改电梯任务状态为4，数据库异常，回滚");
            }
            return AgvTaskSubmitVo.OK(null);
        }else if (LiftTaskStatus.RELEASE_RESOURCE.getMessage().equals(method)){
            //AGV上报离开电梯储位，修改电梯任务状态
            LiftTask liftTask = liftTaskService.selectLIftTask(taskCode);
            boolean b1 = liftTaskService.updateStatus(liftTask.getId(), LiftTaskStatus.LEAVE_LIFT.getCode());
            if (!b1){
                liftLog.error("修改电梯任务状态为8，数据库异常，回滚");
                throw new RuntimeException("修改电梯任务状态为8，数据库异常，回滚");
            }
            return AgvTaskSubmitVo.OK(null);
        }

//        return AgvTaskSubmitVo.ng("未找到该任务");
        return AgvTaskSubmitVo.ng(taskCode);
    }


}
